/// 参数
fn hi(name : &str) {
    println!("hi {}", name);
}

fn nihao(name : &str) {
    println!("nihao {}", name)
}

fn say_what(name : &str, func : fn(&str)) {
    func(name);
}

fn test_parameters() {
    say_what("xiaoming", hi);
    say_what("jorn", nihao);
}

/// 模式
fn print_age((_,age):(&str,i32)) {
    println!("my age is {}", age);
}

fn test_pattern() {
    let jorn = ("jorn",24);
    print_age(jorn);
}

/// 发散函数 diverging
fn test_deiverging() -> ! {
    panic!("this function will never return!")
}

/// 语句和表达式
fn test_statements_expression() {
    //Item声明语句
    let a = 8;
    let b: Vec<f64> = Vec::new();
    let (a, c) = ("hi", false);

    //字面表达式（literal expression）
    ();        // unit type
    "hello";   // string type
    '1';       // character type
    15;         // integer type

    //元组表达式(Tuple expression)
    (0.0, 4.5);
    ("a", 4usize, true);
    (0,);//一个元素的元组
    (0); // zero in parentheses

    //结构体表达式（structure expression）
    //let base = Point3d {x: 1, y: 2, z: 3};
    //Point3d {y: 0, z: 10, .. base};

    //块表达式（block expression）： 块表达式就是用花括号{}括起来的一组表达式的集合，表达式间一般以分号分隔。块表达式的值，就是最后一个表达式的值。
    let x: i32 = { println!("Hello."); 5 };

    //范围表达式（range expression）
    3..;

    //if表达式（if expression）
    let a = 9;
    let b = if a%2 == 0 {"even"} else {"odd"};
}

//高阶函数，函数的所有权是不能转移的，rust中的函数类型，就像是C/C++中的函数指针
//rust的指针类型有两种，一种是引用类型（Reference&），另一种为原始指针（Raw Pointer*）
fn inc(n : i32) -> i32 {
    n+1
}

type IncType = fn(i32)->i32;

fn test_ext_func() {
    let func : IncType = inc;
    println!("3 + 1 = {}", func(3));
    println!("3 + 1 = {}", inc(3));
}

//函数作为参数
fn dec(n : i32) -> i32 {
    n-1
}

fn process(n : i32, func : fn(i32)->i32) -> i32 {//高阶函数
    func(n)
}

fn process2<F>(n : i32, func : F) -> i32
    where F : Fn(i32)->i32 {
    func(n)
}

fn test_ext_func_inparam() {
    println!("3+1={}", process2(3, inc));
    println!("3-1={}", process2(3, dec));
}

fn get_func(n : i32) -> fn(i32)->i32 {
    fn inc(n : i32) -> i32 {
        n+1
    }

    fn dec(n : i32) -> i32 {
        n-1
    }

    if n%2 == 0 {
        inc
    } else {
        dec
    }
}

fn test_ext_func_outparam() {
    let func = get_func(32);
    println!("value = {}", func(32));
}

fn main() {
    //普通参数
    test_parameters();

    //参数模式匹配
    test_pattern();
    //test_deiverging();

    //表达式
    test_statements_expression();

    //高阶函数
    test_ext_func();
    test_ext_func_inparam();
    test_ext_func_outparam();
}